﻿#include "GraphicsBoxItem.h"
#include <GraphicsImageBuilder.h>
#include <GraphicsView.h>
#include <GraphicsImageItem.h>
#include <GraphicsScene.h>
#include <ScaleCommand.h>
#include <StretchCommand.h>
#include <SetModeCommand.h>
#include <BoundingMoveStrategy.h>
#include <GraphicsMoveOperation.h>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QCursor>
#include <QRandomGenerator>

GraphicsBoxItem::GraphicsBoxItem(GraphicsScene* scene, int width, int height)
	:GraphicsBaseItem(GraphicsItemType::Box_Enum, scene, nullptr)
	, m_bcImage(":/images/aiexpandbackground.png")
{
	createBackgroundImage();
	m_data.setScaleSize(QSize(width, height));
	m_data.setRealMaxSize(QSizeF(1024, 1024));
	m_data.setDefaultSize(m_data.getScaleSize().toSize());
	const qreal aspectRatio = (qreal)m_bcImage.width() / (qreal)m_bcImage.height();
	m_data.setBaseItemAspectRatio(aspectRatio);
	createImageItem();
	// 子图元不超出显示
	setFlag(QGraphicsItem::ItemClipsChildrenToShape);
}

QSize GraphicsBoxItem::setMode(const QSize& boxSize, EXpandMode mode)
{
	if (!m_imageItem) {
		return QSize();
	}
	EXpandMode oldMode = m_mode;
	m_mode = mode;
	const GraphicsItemInfo oldItemInfo = m_data.getItemInfo();
	// 记录子图元坐标
	blockSignals(true);
	QMap<GraphicsBaseItem*, GraphicsItemInfo> oldChildsPosMap = getChildsPosMap();
	switch (mode)
	{
	case GraphicsBoxItem::FIX_1_1_Enum:
		setFIX_1_1_Mode(boxSize);
		break;
	case GraphicsBoxItem::FIX_3_4_Enum:
		setFIX_3_4_Mode(boxSize);
		break;
	case GraphicsBoxItem::FIX_4_3_Enum:
		setFIX_4_3_Mode(boxSize);
		break;
	case GraphicsBoxItem::FIX_9_16_Enum:
		setFIX_9_16_Mode(boxSize);
		break;
	case GraphicsBoxItem::FIX_16_9_Enum:
		setFIX_16_9_Mode(boxSize);
		break;
	case GraphicsBoxItem::FREE_Enum:
		setFREE_Mode(boxSize);
		break;
	default:
		break;
	}
	blockSignals(false);
	setImageSelected();
	fitToScreen();
	fitImageToSize();

	// 添加撤销命令
	QMap<GraphicsBaseItem*, GraphicsItemInfo> newChildsPosMap = getChildsPosMap();
	StretchCommand* stretchCommand = new StretchCommand(this,
		oldItemInfo, oldChildsPosMap,
		m_data.getItemInfo(), newChildsPosMap);

	SetModeCommand* setModeCommand = new SetModeCommand(this, stretchCommand, oldMode, mode);
	m_scene->pushCommand(setModeCommand);
	const QSize realSize = getItemData().getRealSize().toSize();
	return realSize;
}

void GraphicsBoxItem::setImage(const QImage& image)
{
	if (!m_imageItem)
		return;
	m_imageItem->setImage(image);
	//m_imageItem->getItemData().setMaskImage(QImage(":/images/bc.png"));
	m_data.setOriginImage(image);
}

GraphicsBoxItem::~GraphicsBoxItem()
{

}

void GraphicsBoxItem::initGraphics()
{
	setSelected(false);
	getOperation<GraphicsMoveOperation>(GraphicsOperationType::MoveOperation_Enum)->setMoveStrategy(std::make_shared<BoundingMoveStrategy>(getItemData()));
	init();
}

GraphicsBoxItemData GraphicsBoxItem::getBoxData()
{
	GraphicsBoxItemData itemData;
	if (!m_imageItem)
		return itemData;

	itemData.boxSize = m_data.getRealSize().toSize();
	itemData.imageSize = m_imageItem->getItemData().getRealSize().toSize();
	itemData.imageTransform = getImageTransform();
	itemData.boxTransform = getBoxTransform();
	itemData.image = m_imageItem->getImage();
	qDebug() << "box数据:" << itemData;
	return itemData;
}

void GraphicsBoxItem::onMaskChanged(const QImage& mask)
{
	QImage temp = mask.copy();
	const int width = temp.width();
	const int height = temp.height();
	// 将alpha大于0的转为255
	uchar* scanLine = nullptr;
	const int stride = width * 4;  // 每行的字节数
	for (int y = 0; y < height; ++y) {
		uchar* scanLine = temp.scanLine(y);
		for (int i = 3, end = stride; i < end; i += 4) {
			if (scanLine[i] != 0) {
				scanLine[i] = 255;
			}
		}
	}
	m_imageItem->getItemData().setMaskImage(temp);
}

QRectF GraphicsBoxItem::getCenterBoxRect()
{
	const QSizeF scaleSize = m_data.getScaleSize();
	const qreal itemScale = m_data.getItemScale();
	const QSizeF centerSize = m_centerBox * itemScale;
	const QPointF point(scaleSize.width() / 2 - centerSize.width() / 2, scaleSize.height() / 2 - centerSize.height() / 2);
	return QRectF(point, centerSize);
}

void GraphicsBoxItem::setFIX_1_1_Mode(const QSize& boxSize)
{
	m_data.setItemMode(GraphicsItemMode::Fix_Enum, 1.0);
	// 计算box的尺寸
	const qreal boxWidth = qMax(boxSize.width(), boxSize.height());
	getItemData().setRealSize(QSizeF(boxWidth, boxWidth));
}

void GraphicsBoxItem::setFIX_3_4_Mode(const QSize& boxSize)
{
	m_data.setItemMode(GraphicsItemMode::Fix_Enum, 3.0 / 4.0);
	// 计算box的尺寸，以高为基准
	const qreal boxWidth = boxSize.height() * (3.0 / 4.0);
	getItemData().setRealSize(QSizeF(boxWidth, boxSize.height()));
}

void GraphicsBoxItem::setFIX_4_3_Mode(const QSize& boxSize)
{
	m_data.setItemMode(GraphicsItemMode::Fix_Enum, 4.0 / 3.0);
	// 计算box的尺寸，以宽为基准
	const qreal boxHeight = boxSize.width() / (4.0 / 3.0);
	getItemData().setRealSize(QSizeF(boxSize.width(), boxHeight));
}

void GraphicsBoxItem::setFIX_9_16_Mode(const QSize& boxSize)
{
	m_data.setItemMode(GraphicsItemMode::Fix_Enum, 9.0 / 16.0);
	// 计算box的尺寸，以高为基准
	const qreal boxWidth = boxSize.height() * (9.0 / 16.0);
	getItemData().setRealSize(QSizeF(boxWidth, boxSize.height()));
}

void GraphicsBoxItem::setFIX_16_9_Mode(const QSize& boxSize)
{
	m_data.setItemMode(GraphicsItemMode::Fix_Enum, 16.0 / 9.0);
	// 计算box的尺寸，以宽为基准
	const qreal boxHeight = boxSize.width() / (16.0 / 9.0);
	getItemData().setRealSize(QSizeF(boxSize.width(), boxHeight));
}

void GraphicsBoxItem::setFREE_Mode(const QSize& boxSize)
{
	m_data.setItemMode(GraphicsItemMode::Free_Enum, 1.0);
	const QSizeF imageRealMinSize = getImageRealMinSize();
	QSizeF newSize = boxSize;
	// 最小尺寸检查
	if (boxSize.width() <= imageRealMinSize.width() / 0.8) {
		newSize.setWidth(imageRealMinSize.width() / 0.8);
	}
	if (boxSize.height() <= imageRealMinSize.height() / 0.8) {
		newSize.setHeight(imageRealMinSize.height() / 0.8);
	}
	getItemData().setRealSize(newSize);
}

void GraphicsBoxItem::init()
{
	moveToParentCenter();
	m_scene->setCenterItem(this);
	onUpdatePinkItemPosition();
}

QVector<double> GraphicsBoxItem::getImageTransform()
{
	QVector<double> transform;
	if (!m_imageItem)
		return transform;
	QSize imageSize = m_imageItem->getImage().size();

	const QRectF boxRect = m_data.getRealRect();
	const QSizeF imageItemSize = m_imageItem->getItemData().getRealSize();
	const qreal angle = m_imageItem->getItemData().getRotateAngle() * M_PI / 180.0;

	const qreal scaleWidthFactor = imageItemSize.width() / (double)imageSize.width();
	const qreal scaleHeightFactor = imageItemSize.height() / (double)imageSize.height();

	transform << scaleWidthFactor * qCos(angle);
	transform << scaleWidthFactor * qSin(angle);
	transform << -scaleHeightFactor * qSin(angle);
	transform << scaleHeightFactor * qCos(angle);

	//transform << qCos(angle);
	//transform << qSin(angle);
	//transform << -qSin(angle);
	//transform << qCos(angle);


	const QPointF imageCenter = m_imageItem->getItemData().getRealRect().center();
	const QPointF boxCenter(boxRect.width() / 2.0, boxRect.height() / 2.0);
	// transform << (imageCenter.x() - boxCenter.x()) + (double)boxRect.width() / 2.0;
	// transform << (imageCenter.y() - boxCenter.y()) + (double)boxRect.height() / 2.0;
	transform << imageCenter.x();
	transform << imageCenter.y();
	return transform;
}

QVector<double> GraphicsBoxItem::getBoxTransform()
{
	QVector<double> transform;
	if (!m_imageItem)
		return transform;
	const QRectF boxRect = m_data.getRealRect();
	const QSizeF imageItemSize = m_imageItem->getItemData().getRealSize();
	transform << 1 << 0 << 0 << 1;
	transform << boxRect.width() / 2.0 << boxRect.height() / 2.0;
	return transform;
}


void GraphicsBoxItem::fitToScreen()
{
	// 计算view的缩放因子
	const qreal scaledFactor = getFitToScreenFactor(m_data.getRealSize());
	m_data.setItemScale(scaledFactor);
	// 将图元移到场景中心
	moveToParentCenter();
	updateAbsorptionLinePos();
	if (m_scene->getView()) {
		emit m_scene->getView()->sigViewScaleChanged();
	}
}

qreal GraphicsBoxItem::getFitToScreenFactor(const QSizeF& boxRealsize)
{
	if (!m_scene)
		return 0;

	GraphicsView* view = m_scene->getView();

	if (!view)
		return 0;

	const QSize viewSize = view->size();
	const qreal viewScale = view->getViewScale();

	// 视图宽高
	const int viewWidth = viewSize.width();
	const int viewHeight = viewSize.height();

	// 扩区图元实际宽高(排除缩放)
	const qreal boxWidth = boxRealsize.width();
	const qreal boxHeight = boxRealsize.height();
	const qreal boxRate = boxWidth / boxHeight;

	// 计算view的缩放因子
	qreal scaledFactor = 1;

	// 自适应屏幕理想宽高
	const int idealHeight = ((qreal)viewHeight / viewScale) * 0.9;
	const int idealFitWidth = (qreal)idealHeight * boxRate;
	if (idealFitWidth <= viewWidth) {
		scaledFactor = (qreal)idealFitWidth / (qreal)boxWidth;
	}
	else {
		// 自适应屏幕理想宽
		const int idealWidth = ((qreal)viewWidth / viewScale) * 0.9;
		const int idealFitHeight = (qreal)idealWidth / boxRate;
		scaledFactor = (qreal)idealWidth / (qreal)boxWidth;
	}
	return scaledFactor;
}

void GraphicsBoxItem::setImageSelected()
{
	m_scene->setSelectItem(m_imageItem);
}

void GraphicsBoxItem::setMaskVisable(bool visable)
{
}

void GraphicsBoxItem::test1()
{
	GraphicsBoxItemData boxData = getBoxData();
	//m_imageItem->getItemData().setRotateAngle(45);
}

void GraphicsBoxItem::test2(double scale)
{
	setMode(QSize(800, 600), EXpandMode::FREE_Enum);
	GraphicsScene* pScene = dynamic_cast<GraphicsScene*>(scene());
	pScene->printInfo();
}

void GraphicsBoxItem::test3()
{
	setMode(QSize(768, 768), EXpandMode::FIX_1_1_Enum);
}

void GraphicsBoxItem::test4()
{
	setMode(QSize(768, 768), EXpandMode::FIX_4_3_Enum);
	GraphicsScene* pScene = dynamic_cast<GraphicsScene*>(scene());
	pScene->printInfo();
}

void GraphicsBoxItem::test5()
{
	//GraphicsBoxItemData boxData = getBoxData();
}

void GraphicsBoxItem::createImageItem()
{
	GraphicsImageBuilder builder(this, m_scene);
	m_imageItem = builder.build();
	addChild(m_imageItem);
	connect(&m_imageItem->getItemData(), &GraphicsBaseItemData::sigMoving, [=] {
		m_isVisabledCenterBox = true;
		});
}


void GraphicsBoxItem::createBackgroundImage()
{
	const int width = m_bcImage.width();
	const int height = m_bcImage.height();

	// 背景图拼接
	QImage bigImage(width * 4, height * 4, QImage::Format_ARGB32_Premultiplied);
	QPainter painter(&bigImage);
	painter.setCompositionMode(QPainter::CompositionMode_Source);
	painter.fillRect(QRect(0, 0, width * 4, height * 4), Qt::transparent);
	for (int i(0); i < 4; ++i) {
		for (int j(0); j < 4; ++j) {
			painter.drawImage(width * i, height * j, m_bcImage);
		}
	}
	painter.end();
	m_bcImage = bigImage;
}

QMap<GraphicsBaseItem*, GraphicsItemInfo> GraphicsBoxItem::getChildsPosMap()
{
	QMap<GraphicsBaseItem*, GraphicsItemInfo> childPosMap;
	for (GraphicsBaseItem* child : m_data.getChilds()) {
		GraphicsItemInfo itemInfo = child->getItemData().getItemInfo();
		childPosMap[child] = itemInfo;
	}
	return childPosMap;
}

QSizeF GraphicsBoxItem::getImageRealMinSize()
{
	QSizeF imageKeepRatioSize = m_imageItem->getItemData().getRealMinSize();
	const qreal aspectRatio = m_imageItem->getItemData().getBaseItemAspectRatio();
	if (aspectRatio >= 1) {
		// 宽大于高，以高为最小边计算宽
		const qreal width = imageKeepRatioSize.height() * aspectRatio;
		imageKeepRatioSize.setWidth(width);
	}
	else {
		// 高大于宽，以宽为最小边计算高
		const qreal height = imageKeepRatioSize.width() / aspectRatio;
		imageKeepRatioSize.setHeight(height);
	}
	return imageKeepRatioSize;
}

void GraphicsBoxItem::fitImageToSize()
{
	// 自适应屏幕后的尺寸
	m_imageItem->fitImageToSize(1.0, false);
}

void GraphicsBoxItem::scaleGraphics(GraphicsPinkItemType type, const QPointF& delta)
{
	if (m_data.getExpandMode() == GraphicsItemMode::Fix_Enum) {
		stretchGraphicsOnCornerKeepRatio(type, delta);
	}
	else {
		stretchGraphicsOnCorner(type, delta);
	}
}

void GraphicsBoxItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
	const QSizeF scaleSize = m_data.getScaleSize();
	if (scaleSize.width() <= 0 || scaleSize.height() <= 0)
		return;

	painter->setRenderHints(QPainter::Antialiasing, true);
	painter->setRenderHint(QPainter::SmoothPixmapTransform, true);
	painter->save();
	const QColor borderColor = m_data.getBorderColor();
	QPen pen(borderColor);
	const int penWidth = m_data.getPenWidth();
	pen.setWidth(penWidth);
	painter->setPen(pen);
	painter->drawRect(QRectF(0, 0, scaleSize.width(), scaleSize.height()));

	QImage cropImg = m_bcImage.copy(0, 0, scaleSize.toSize().width(), scaleSize.toSize().height());
	// 原图尺寸大小
	const QRectF sourceImageRect(QPointF(0, 0), scaleSize);
	const QRectF dstImageRect(QPointF(0, 0), scaleSize);
	painter->drawImage(dstImageRect, cropImg, sourceImageRect);

	// 绘制中心虚线框
	if (m_isVisabledCenterBox) {
		pen.setColor(QColor(159, 164, 175));
		pen.setStyle(Qt::DashLine);
		painter->setPen(pen);
		painter->drawRect(getCenterBoxRect());
	}

	painter->restore();
}

void GraphicsBoxItem::operationDone(GraphicsPinkItemType type, const QPointF& mousePoint)
{
	fitToScreen();
	// Box图元缩放
	if (type < GraphicsPinkItem::CornerEnd_Enum) {
		const GraphicsItemInfo itemInfo = m_data.getItemInfo();
		// 记录子图元坐标
		QMap<GraphicsBaseItem*, GraphicsItemInfo> curChildsPosMap = getChildsPosMap();

		// 子图元的位置
		ScaleCommand* scaleCommand = new ScaleCommand(this,
			m_data.getPressItemInfo(), getChildPressedContextMap(),
			itemInfo, curChildsPosMap);
		m_scene->pushCommand(scaleCommand);
	}
	GraphicsBaseItem::operationDone(type, mousePoint);
}
